#include "hardware.h"
#include "sys.h"

#include <avr/pgmspace.h>

#define LCD_E1   PORTB |= (1<<bo_LCD)
#define LCD_E0   PORTB &= ~(1<<bo_LCD)
#define LCD_W    PORTB &= ~(1<<bo_RW)
#define LCD_R    PORTB |= (1<<bo_RW)
#define LCD_DATA PORTB |= (1<<bo_RS)
#define LCD_CMD  PORTB &= ~(1<<bo_RS)
  
#define LCD_PAUSE asm("nop");asm("nop");asm("nop");\
                  asm("nop");asm("nop");asm("nop");\
                  asm("nop");asm("nop");asm("nop");\
                  asm("nop");asm("nop");asm("nop");
                  
void LCD_Write(BYTE D)
{
Flags |= F_BBusy;
BUS_OUT;
PORTF = D;
LCD_PAUSE;
LCD_E1;
LCD_PAUSE;
LCD_E0;
asm("nop");
BUS_IN;                                                          
Flags &= ~F_BBusy;
}

BYTE LCD_Read(void)
{
BYTE D;
Flags |= F_BBusy;
LCD_R;
LCD_PAUSE;
LCD_E1;
LCD_PAUSE;
D = PINF;
LCD_E0;
LCD_W;
Flags &= ~F_BBusy;
return D;
}

void LCD_Wait(void)
{
BYTE D;
LCD_CMD;
LCD_R;
do {
  LCD_PAUSE;
  LCD_E1;
  Flags |= F_BBusy;
  LCD_PAUSE;
  D = PINF;
  LCD_E0;
  Flags &= ~F_BBusy;
  } while(D & 0x80);
LCD_PAUSE;
LCD_W;
}


void LCD_Put(char C)
{
LCD_Wait();
LCD_DATA;
LCD_Write(C);
}

void LCD_Init(void)
{
LCD_W;
LCD_E0;
LCD_CMD;
PAUSE(12);
LCD_Write(0x30);
PAUSE(4);
LCD_Write(0x30);
PAUSE(1);
LCD_Write(0x30);
LCD_Wait();
LCD_Write(0x38);
LCD_Wait();
LCD_Write(0x0F);
LCD_Wait();
LCD_Write(0x01);
}

void LCD_Com(BYTE C)
{
LCD_Wait();
LCD_CMD;
LCD_Write(C);
}

void LCD_Type(char * S)
{
while(*S) {
  LCD_Wait();
  LCD_DATA;
  LCD_Write(*S++);
  }
}

void LCD_Blank(BYTE N)
{
BYTE i;
for(i=0; i<N; i++)
  {
  LCD_Wait();
  LCD_DATA;
  LCD_Write(' ');
  }
}

void LCD_Sym(BYTE Addr, BYTE * Sym)
{
LCD_Wait();
LCD_CMD;
LCD_Write(0x40|(Addr<<3));
for(BYTE i=0; i<8; i++) 
  {
  LCD_Wait();
  LCD_DATA;
  LCD_Write(pgm_read_byte (&Sym[i]));
  }
}

char H[]  ="0123456789ABCDEF";

void Hex(BYTE D)
{
LCD_Put(H[(D&0xF0)>>4]);
LCD_Put(H[(D&0x0F)]);
}

void Bin(BYTE D)
{
BYTE i, M;
for(i = 0, M = 0x80; i < 8; i++, M >>= 1)
  LCD_Put((D & M) ? '+' : '-');
}
